package file

import (
	"archive/tar"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// Tar 打成 tar 包
func Tar(source, targetPath string) error {
	baseName := filepath.Base(source)

	now := time.Now()
	formatted := now.Format("0102_15_04_05")
	targetTarPath := filepath.Join(targetPath, baseName+"-"+formatted+".tar")
	tarFile, err := os.Create(targetTarPath)

	if err != nil {
		return err
	}
	defer tarFile.Close()

	// 创建一个新的tar.Writer
	tarWriter := tar.NewWriter(tarFile)
	defer tarWriter.Close()

	// 使用gzip.Writer进行压缩（如果需要.tar.gz文件）
	// gzipWriter := gzip.NewWriter(tarFile)
	// defer gzipWriter.Close()

	// 遍历目录并添加文件到tar包
	err = filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 创建tar头信息
		// join := filepath.Join(baseName, strings.Replace(path, source, "", 1))
		header, err := tar.FileInfoHeader(info, "")
		if err != nil {
			return err
		}

		// 设置头信息中的名称，确保只包含相对于源目录的路径
		// tar 包中的目录分隔符不管在什么平台都是 /，而不应该使用 filepath.Separator
		p1 := strings.ReplaceAll(path, "\\", "/")
		p2 := strings.ReplaceAll(source, "\\", "/")
		header.Name = strings.Replace(p1, p2, baseName, 1)

		// 写入tar头部信息
		if err := tarWriter.WriteHeader(header); err != nil {
			return err
		}

		// 如果是目录，则不需要写入内容
		if !info.IsDir() {
			// log.Printf("this is a file %s\n", path)
			file, err := os.Open(path)
			if err != nil {
				return err
			}
			defer file.Close()

			// 将文件内容写入tar包
			_, err = io.Copy(tarWriter, file)
			if err != nil {
				return err
			}
		} else {
			// log.Println("this is a dir")
		}

		return nil
	})

	if err != nil {
		return err
	}

	log.Printf("tar 打包成功 %s\n", targetTarPath)

	return nil
}
